package favorGenericMethods;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;

/**
 * Created with IntelliJ IDEA.
 * User: Georgiana.Scarlat
 * Date: 8/30/12
 * Time: 11:21 AM
 *
 */
public class UsefulFunctions {

    /* we have also applied producer-consumer principle*/
    public static <T> void map(Iterable<? extends T> source,Collection<? super T> destination, UnaryFunction<T> function){

        for (T itElem : source) {
            T element = function.applyUnaryFunction(itElem);
            destination.add(element);
        }
    }

    public static <T> T reduce(Iterable<? extends T> source, BinaryFunction<T> function, T init){

        for(T itElem:source){
           init = function.applyBinaryFunction(init,itElem);
        }
        return init;
    }

    public static void main(String[] args) {

        Iterable<Integer> soureElems = getSomeIntegers();
        Collection<Integer> destinationElems = new LinkedList<Integer>();
        UnaryFunction<Integer> increment = getIncrementFunction();
        BinaryFunction<Integer> sum = getSumFunction();

        map(soureElems,destinationElems,increment);

        System.out.println(destinationElems);

        System.out.println(UsefulFunctions.<Integer>reduce(soureElems,sum,0));
    }

    private static BinaryFunction<Integer> getSumFunction() {
        return new BinaryFunction<Integer>() {
            @Override
            public Integer applyBinaryFunction(Integer first, Integer second) {
                return first+second;
            }
        };
    }

    private static UnaryFunction<Integer> getIncrementFunction() {
        return new UnaryFunction<Integer>() {
            @Override
            public Integer applyUnaryFunction(Integer elem) {
                  return ++elem;
            }
        };
    }

    public static Iterable<Integer> getSomeIntegers() {

        Collection<Integer> integers = new ArrayList<Integer>();
        integers.add(10);
        integers.add(11);
        integers.add(12);
        return integers;
    }
}
